package com.lenovo.redission.redission.controller;


import com.lenovo.redission.redission.service.RedisTestService;
import lombok.extern.log4j.Log4j2;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@Log4j2
@RestController
public class RedisTestController {

    @Autowired
    private RedisTestService redisTestService;

    @Autowired(required = false)
    private RedissonClient redissonClient;

    @GetMapping("/lock")
    public void lock() {
        RLock rLock = redissonClient.getLock("test");
        try {
            //阻塞等待
            //lock(long leaseTime, TimeUnit unit) =  lock(leaseTime, unit, false);
            // = lock(-1, null, false);
            rLock.lock();
            //业务代码

        } finally {
            rLock.unlock();
        }
    }

    @GetMapping("/trylock")
    public void tryLock() {
        RLock rLock = redissonClient.getLock("test");
        boolean lock = false;
        try {
            //尝试获取锁 有等待时间

            //rLock.tryLock() = rLock.tryAcquireOnceAsync(-1, -1, null, threadId)  尝试加锁一次
            //rLock.tryLock( long waitTime, TimeUnit unit) = tryLock(waitTime, -1, unit);
            //rLock.tryLock( long waitTime, long leaseTime, TimeUnit unit)

            //获取到锁的最长等待时间
            long waitTime = 1L;
            long leaseTime = 30L;
            TimeUnit unit = TimeUnit.SECONDS;
            lock = rLock.tryLock(waitTime, leaseTime, unit);


            //业务代码

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock) {
                rLock.unlock();
            }
        }
    }

    AtomicInteger age = new AtomicInteger(0);


    @GetMapping("/mlock")
    public void MockHttpServletRequestBuilder() throws InterruptedException {
        int num = 3;

        //https://blog.csdn.net/zhaokuner/article/details/114374585
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(num);
        executor.setMaxPoolSize(num);
        executor.setQueueCapacity(num);
        executor.setKeepAliveSeconds(1);
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();


        CyclicBarrier barrier = new CyclicBarrier(num);
        CountDownLatch downLatch = new CountDownLatch(num);
        for (int i = 0; i < num; i++) {
            executor.execute(() -> {
                try {
                    barrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
                System.out.println(barrier.getParties());
                redisLockTest();
                downLatch.countDown();
                System.out.println(downLatch.getCount());
            });
        }

        downLatch.await();

    }

    @GetMapping("/redislock")
    public void redisLockTest() {
//        this.redisTestService.redisLockTest();
//        log.info("redislock start {}", Thread.currentThread().getId());
        Object obj = this.redisTestService.redisLockAnnotationTest();
        log.info(obj);
//        RedisSerializableModel model = new RedisSerializableModel();
//        model.setName("redisLock");
//        model.setAge(age.incrementAndGet());
//        this.redisTestService.redisLockAnnotationObjTest(model);
//        model.setAge(1);
//        this.redisTestService.redisLockAnnotationObjTestSpEL(model);
        log.info("redislock end {}", Thread.currentThread().getId());
    }

}
